package cn.yueranzs.utils;

import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.util.IdUtil;
import cn.yueranzs.config.AliyunOSSConfig;
import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

/**
 * @author yueranzs
 * @date 2021-06-30 14:14
 */
@Component
public class AliyunOSSUtil {

    private static AliyunOSSConfig aliyunOSSConfig;


    @Autowired
    private void setAliyunOSSConfig(AliyunOSSConfig aliyunOSSConfig){
        AliyunOSSUtil.aliyunOSSConfig = aliyunOSSConfig;
    }

    /**
     * 获取当天日期
     * @return
     */
    public static String getNowDate(){
        return new SimpleDateFormat("yyyy/MM/dd").format(new Date());
    }

    /**
     * 保存图片到阿里云OSS
     * @param file 文件
     * @param type 类型 存储规范：bucket域名 + images + 类型(头像、商品图片等等) + 日期 + 图片文件名
     * @return
     */
    public static String uploadFile(MultipartFile file, String type) throws IOException {
//        OSS ossClient = new OSSClientBuilder().build(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        OSS ossClient = new OSSClientBuilder().build(aliyunOSSConfig.getEndPoint(), aliyunOSSConfig.getAccessKeyId(), aliyunOSSConfig.getAccessKeySecret());

        //获取上传文件输入流
        InputStream inputStream = file.getInputStream();
        //获取文件名称
        String fileName = file.getOriginalFilename();

        //在文件名称里面添加随机唯一的值
        String uuid = IdUtil.fastSimpleUUID().toUpperCase(Locale.ROOT);
        //拼接名称：fileName = uuid-123456.jpg
        fileName = uuid + "-" + fileName;

        //拼接日期：fileName = 2021/07/01/uuid-123456.jpg
        fileName = getNowDate() + "/" + fileName;

        //判断OSS的存储空间bucket是否存在
        if (!ossClient.doesBucketExist(aliyunOSSConfig.getBucketName())) {
            // 创建CreateBucketRequest对象。
            CreateBucketRequest createBucketRequest = new CreateBucketRequest(aliyunOSSConfig.getBucketName());
            // 如果创建存储空间的同时需要指定存储类型和数据容灾类型, 请参考如下代码。
            // 此处以设置存储空间的存储类型为标准存储为例介绍。
            createBucketRequest.setStorageClass(StorageClass.Standard);
            // 数据容灾类型默认为本地冗余存储，即DataRedundancyType.LRS。如果需要设置数据容灾类型为同城冗余存储，请设置为DataRedundancyType.ZRS。
//            createBucketRequest.setDataRedundancyType(DataRedundancyType.ZRS);
            // 设置存储空间的权限为公共读，默认为私有。
            createBucketRequest.setCannedACL(CannedAccessControlList.Default);
            // 创建存储空间。
            ossClient.createBucket(createBucketRequest);
        }

        //调用OSS上传：images/Head-portrait/2021/07/01/uuid-123456.jpg
        ossClient.putObject(aliyunOSSConfig.getBucketName(),aliyunOSSConfig.getFileDir() + type + "/" + fileName,inputStream);

        //关闭OSSClient
        ossClient.shutdown();
        return aliyunOSSConfig.getFileDir() + type + "/" + fileName;
    }

    /**
     * 使用签名URL进行临时授权
     * 获取OSS文件流路径：临时url路径供外部访问，数据库只保存存储在OSS中原始路径
     * @param fileName 源文件路径，除bucket前缀域名等
     * @param style 设置图片样式大小
     * @return
     */
    public static String getFileUrl(String fileName,String style){
//        OSS ossClient = new OSSClientBuilder().build(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        OSS ossClient = new OSSClientBuilder().build(aliyunOSSConfig.getEndPoint(), aliyunOSSConfig.getAccessKeyId(), aliyunOSSConfig.getAccessKeySecret());

        // 设置URL过期时间为1小时，默认这里是int型，转换为long型即可
        Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
        // 封装整体作为参数去OSS取URL
        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(aliyunOSSConfig.getBucketName(), fileName, HttpMethod.GET);
        req.setExpiration(expiration);
        if (style != null) {
            req.setProcess(style);
        }
        //关闭OSSClient
        ossClient.shutdown();
        //把上传后的文件路径返回，此处返回原样返回
        return ossClient.generatePresignedUrl(req).toString();
    }

    /**
     * 使用签名URL进行临时授权
     * 获取OSS文件流路径：临时url路径供外部访问，数据库只保存存储在OSS中原始路径
     * @param endPoint 外网访问节点地址
     * @param bucketName bucket名称
     * @param fileName 文件地址
     * @param style 样式名称
     * @return
     */
    public static String getFileUrl(String endPoint,String bucketName,String fileName,String style){
//        OSS ossClient = new OSSClientBuilder().build(endPoint, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        OSS ossClient = new OSSClientBuilder().build(aliyunOSSConfig.getEndPoint(), aliyunOSSConfig.getAccessKeyId(), aliyunOSSConfig.getAccessKeySecret());

        // 设置URL过期时间为1小时，默认这里是int型，转换为long型即可
        Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
        // 封装整体作为参数去OSS取URL
        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, fileName, HttpMethod.GET);
        req.setExpiration(expiration);
        if (style != null) {
            req.setProcess(style);
        }
        //关闭OSSClient
        ossClient.shutdown();
        //把上传后的文件路径返回，此处返回原样返回
        return ossClient.generatePresignedUrl(req).toString();
    }

    /**
     * 获取OSS文件流
     * 注：通过接口直接返回整个文件
     * @param filePath 文件路径
     * @return
     */
    public static InputStream getOSSFileStream(String filePath){
//        OSS ossClient = new OSSClientBuilder().build(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        OSS ossClient = new OSSClientBuilder().build(aliyunOSSConfig.getEndPoint(), aliyunOSSConfig.getAccessKeyId(), aliyunOSSConfig.getAccessKeySecret());

        OSSObject ossClientObject = ossClient.getObject(aliyunOSSConfig.getBucketName(), filePath);
        //关闭OSSClient
        ossClient.shutdown();
        return ossClientObject.getObjectContent();
    }

    /**
     * 删除单个文件
     * @param fileName 文件地址
     * @return
     */
    public static void deleteFile(String fileName){
//        OSS ossClient = new OSSClientBuilder().build(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        OSS ossClient = new OSSClientBuilder().build(aliyunOSSConfig.getEndPoint(), aliyunOSSConfig.getAccessKeyId(), aliyunOSSConfig.getAccessKeySecret());

        // 删除文件或目录。如果要删除目录，目录必须为空。
        ossClient.deleteObject(aliyunOSSConfig.getBucketName(), fileName);
        // 关闭OSSClient。
        ossClient.shutdown();
    }

    /**
     * 批量删除文件
     * @param endPoint 节点地址
     * @param bucketName bucket名称
     * @param fileNames 文件地址集合
     * @return
     */
    public static List<String> deleteFiles(String endPoint,String bucketName,List<String> fileNames){
//        OSS ossClient = new OSSClientBuilder().build(endPoint, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        OSS ossClient = new OSSClientBuilder().build(endPoint, aliyunOSSConfig.getAccessKeyId(), aliyunOSSConfig.getAccessKeySecret());

        DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(fileNames).withEncodingType("UTF-8"));
        List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
        deletedObjects.forEach(obj -> obj=URLDecoder.decode(obj, Charset.defaultCharset()));
        // 关闭OSSClient。
        ossClient.shutdown();
        return deletedObjects;
    }
    /**
     * 批量删除文件
     * @param fileNames 文件地址集合
     * @return
     */
    public static List<String> deleteFiles(List<String> fileNames){
//        OSS ossClient = new OSSClientBuilder().build(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        OSS ossClient = new OSSClientBuilder().build(aliyunOSSConfig.getEndPoint(), aliyunOSSConfig.getAccessKeyId(), aliyunOSSConfig.getAccessKeySecret());

        DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(aliyunOSSConfig.getBucketName()).withKeys(fileNames).withEncodingType("UTF-8"));
        List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
        deletedObjects.forEach(obj -> obj=URLDecoder.decode(obj, Charset.defaultCharset()));
        // 关闭OSSClient。
        ossClient.shutdown();
        return deletedObjects;
    }

    /**
     * 相同bucket下进行拷贝文件，必须加文件名和后缀
     * @param sourceFilePath 源文件完整路径
     * @param targetPath 目标路径
     * @return 目标路径文件地址
     */
    public static void cpFile(String sourceFilePath,String targetPath){
//        OSS ossClient = new OSSClientBuilder().build(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        OSS ossClient = new OSSClientBuilder().build(aliyunOSSConfig.getEndPoint(), aliyunOSSConfig.getAccessKeyId(), aliyunOSSConfig.getAccessKeySecret());

        CopyObjectResult result = ossClient.copyObject(aliyunOSSConfig.getBucketName(), sourceFilePath, aliyunOSSConfig.getBucketName(), aliyunOSSConfig.getFileDir() + targetPath);
        // 关闭OSSClient。
        ossClient.shutdown();
    }
}
